<?php
/*
Plugin Name: Our Todo List
Plugin URI: http://wordpress.byexamples.com/2007/01/29/our-todo-list-plugin
Description: A simple todo list to share ideas/todos with blog members. All members work as a team to manipulate the list under "Manage". A variant derived from AbstractDimension's Todo List Plugin.
Version: 2.0
Author: Wordpress By Examples 
Author URI: http://wordpress.byexamples.com


Copyright 2007  Wordpress By Examples  <http://wordpress.byexamples.com>
Copyright 2006  Abstract Dimension  <http://abstractdimension.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

    // For Abstract Dimension's TodoList users:
    //
    //   This plugin shares the same database table with 
    //   Abstract Dimension's TodoList.
    //
    //   If you don't want them to share the same table.
    //   change the table name 'todolist' to 'ourtodolist'

global $table_prefix;
$otd_tablename       = $table_prefix . 'todolist';
$otd_message         = '';
$otd_location        = get_settings('siteurl') . '/wp-admin/edit.php?page=' . otd_plugin_basename(__FILE__);
$otd_option_location = get_settings('siteurl') . '/wp-admin/options-general.php?page=' . otd_plugin_basename(__FILE__);

load_plugin_textdomain('otd',
            'wp-content/plugins/' . dirname(otd_plugin_basename(__FILE__)) );

function otd_runInclude ()
{
    $path = ABSPATH . WPINC;
    $incfile = $path . '/pluggable-functions.php';
    $incfile_ella = $path . '/pluggable.php';

    if ( is_readable($incfile) ) { 
        require_once($incfile);      
    }
    else if ( is_readable($incfile_ella) ) { 
        require_once($incfile_ella); 
    }
    else {
        echo "Could not read pluggable.php or pluggable-functions.php under $path/.";
        exit;
    }
}

if ( function_exists('add_action') )
{
    otd_runinclude();
    get_currentuserinfo();  // For WP v2.0.x, current_user_can() need it

    add_action('activate_'.otd_plugin_basename(__FILE__), 'otd_activate');

    if ( function_exists('current_user_can') )  // WP >= v2.0
    {
        add_action('admin_menu', 'otd_load_option_panel');

        if ( current_user_can('use_ourtodolist') )
        {
            add_action('admin_menu', 'otd_load_manage_panel');
            add_action('activity_box_end', 'otd_todo_in_activity_box');
        }
    }
    else  // WP < v2.0  - no role-capability feature
    { 
        add_action('admin_menu', 'otd_load_manage_panel');
        add_action('activity_box_end', 'otd_todo_in_activity_box');
    }
}

function otd_load_manage_panel () 
{
    add_management_page(__('OurTodo', 'otd'), __('OurTodo', 'otd'), 1, otd_plugin_basename(__FILE__), 'otd_manage_panel');
}
function otd_load_option_panel () 
{
    add_options_page(__('OurTodo', 'otd'), __('OurTodo', 'otd'), 8, otd_plugin_basename(__FILE__), 'otd_option_panel');
}


///////////////////////////  Activation

function otd_activate () 
{
    global $otd_tablename,  $wpdb, $userdata, $wp_roles;
    get_currentuserinfo();       

    if( $wpdb->get_var("show tables like '$otd_tablename'") != $otd_tablename ) 
    {   
        $sql = "CREATE TABLE $otd_tablename (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        author bigint(20) NOT NULL,
        status tinyint(1) DEFAULT '0' NOT NULL,
        priority tinyint(1) NOT NULL,
              todotext text NOT NULL,
        UNIQUE KEY id (id)
        );";

        require_once(ABSPATH . 'wp-admin/upgrade-functions.php');
        dbDelta($sql);

        $welcome_text = addslashes( __('This is Our Todo List plugin! You can use it to manage and share a list of tasks/thoughts with all members.', 'otd') );

        $insert = "INSERT INTO $otd_tablename ".
                  "(author,status,priority,todotext) ".
                  "VALUES ($userdata->ID,0,1,'$welcome_text')";

        $results = $wpdb->query($insert);
    }

    if ( function_exists('current_user_can') )  // WP >= v2.0
    { 
        otd_update_whocanuse( array_keys($wp_roles->role_names) ); 
    }
}


////////////////////////  Logic 

function otd_option_controller () {
    global $otd_message;

    $otd_action = $_POST['otd_action'];
    $otd_message = '';

    switch ($otd_action) {
        case 'updatetdopt':
        $whocanuse = $_POST['otd_whocanuse'];
        otd_update_whocanuse($whocanuse);
        $otd_message = __('Updated.', 'otd');
        break;
    }
}

function otd_controller ()
{
    global $otd_message;

    $otd_action = $_POST['otd_action'];
    if ( empty($otd_action) ) { $otd_action = $_GET['otd_action']; }
    if ( empty($otd_action) ) { $otd_action = ''; }

    $otd_message = '';
                  
    switch ($otd_action)
    {
        case 'addtodo':
        $todotext = $_POST['otd_description'];
        $priority = $_POST['otd_priority'];
        otd_insert($todotext, $priority);
        $otd_message = __('New todo item has been added.', 'otd'); 
        break;

        case 'comptd':
        $id = $_GET['id'];
        otd_complete($id, '1');
        $otd_message = __('Todo item has been marked completed.', 'otd');
        break;

        case 'trashtd':
        $id = $_GET['id'];
        otd_delete($id);
        $otd_message = __('Todo item has been deleted.', 'otd');
        break;

        case 'updatetd':
        $id = $_POST['id'];
        $todotext = $_POST['otd_description'];
        $priority = $_POST['otd_priority'];
        otd_update($id, $priority, $todotext);
        $otd_message = __('Todo item has been updated.', 'otd');
        break;

        case 'setuptd':
        otd_activate();
        $otd_message = __('Todo database table has been installed.', 'otd');
        break;

        case 'purgetd':
        otd_purge();
        $otd_message = __('Completed todo items have been purged.', 'otd');
        break;

        case 'uncomptd':
        $id = $_GET['id'];
        otd_complete($id, '0');
        $otd_message = __('Todo item has been marked uncompleted.', 'otd');
        break;
   }
}

function otd_insert ($todotext, $priority)
{
    global $otd_tablename,  $wpdb, $userdata;
    get_currentuserinfo();

    $insert = "INSERT INTO $otd_tablename ".
              "(author,status,priority,todotext) ".
              "VALUES ($userdata->ID, 0, $priority,'$todotext')";

    $results = $wpdb->query( $insert );
}

function otd_update ($id, $priority, $todotext)
{
    global $otd_tablename, $wpdb, $userdata;
    get_currentuserinfo();

    $update = "UPDATE $otd_tablename ".
              "SET priority = '$priority', todotext = '$todotext', ". 
              "author = '$userdata->ID' WHERE id = '$id'";

    $results = $wpdb->query( $update );
}

function otd_delete ($id)
{
    global $otd_tablename,  $wpdb;
    $delete = "DELETE FROM $otd_tablename WHERE id = '$id'";
    $results = $wpdb->query( $delete ); 
}

function otd_complete ($id, $status)
{
    global $otd_tablename,  $wpdb;
    $update = "UPDATE $otd_tablename SET status = '$status' WHERE id = '$id'";
    $results = $wpdb->query( $update ); 
}

function otd_get_todo ($id)
{
    global $otd_tablename, $wpdb;

    $edit = "SELECT * FROM $otd_tablename WHERE id = '$id' LIMIT 1";
    $result = $wpdb->get_row( $edit );
    return $result;
}

function otd_purge ()
{
    global $otd_tablename,  $wpdb;

    $purge = "DELETE FROM $otd_tablename WHERE status = '1'";
    $results = $wpdb->query( $purge );
}

function otd_update_whocanuse ($roles)
{
    global $wp_roles;
    $wp_roles->WP_Roles();

    if ( empty($roles) || ! is_array($roles) ) { $roles = array(); }

    $who_can = $roles;
    $who_cannot = array_diff( array_keys($wp_roles->role_names), $roles);

    foreach ($who_can as $role) {
        $wp_roles->add_cap($role, 'use_ourtodolist');
    }
    foreach ($who_cannot as $role) {
        $wp_roles->remove_cap($role, 'use_ourtodolist');
    }
}



////////////////////////////  UI


/* Display UI to manage option */
function otd_option_panel() 
{
    otd_option_controller();

    global $wp_roles, $otd_message;
    $wp_roles->WP_Roles();
?>

<?php if ( !empty($otd_message) ) : ?>
<div id="message" class="updated fade"><p><?php echo $otd_message; ?></p></div>
<?php endif; ?>

<div class="wrap">
<h2><?php _e('Our Todo List', 'otd'); ?></h2>
<h3><?php _e('Who can use Our Todo List?', 'otd'); ?></h3>
<form method="post">
<?php
foreach ($wp_roles->role_names as $roledex => $rolename) 
{
    $role = $wp_roles->get_role($roledex);
    $checked = $role->has_cap('use_ourtodolist') ? 'checked="checked"' : '';
    $readonly = ($roledex == 'administrator') ? 'readonly="readonly"'  : '';

    echo '<p><input type="checkbox" '.$readonly.' '.$checked.' id="'.$roledex.'_option" ';
    echo 'name="otd_whocanuse[]" value="'.$roledex.'" /> ';
    echo '<label for="'.$roledex.'_option" >'.$rolename.'</label></p>'. "\n";
}
?>
    <input type="hidden" name="otd_action" value="updatetdopt" />
    <p class="submit"><input type="submit" name="submit" value="<?php _e('Update Options &raquo', 'otd'); ?>" /></p>
</form>
</div>
<?php
}


/* Display UI to manage todolist  */
function otd_manage_panel()
{
    otd_controller();

    global $wpdb, $otd_tablename, $otd_location, $otd_message;
    $priority = array( 
                  0 => __('Important', 'otd'),
                  1 => __('Normal', 'otd'),
                  2 => __('Low', 'otd')
              );
?>

<?php if ( ! empty($otd_message) ) : ?>
<div id="message" class="updated fade"><p><?php echo $otd_message; ?></p></div>
<?php endif; ?>

<?php
 if($_GET['otd_action'] == 'edittd')
 {
    $id = $_GET['id'];
    $todo = otd_get_todo($id);

    $selection = '';
    for ($i = 0; $i < count($priority); $i++)
    {
        $selected = ($todo->priority == $i) ? 'selected="selected"' : '';
        $selection .= "  <option value=\"$i\" $selected>{$priority[$i]}</option>\n";
    }
?>
<div class="wrap">
 <h2><?php _e('Edit Todo', 'otd') ?></h2>
 <form method="post">
    <table class="editform" width="100%" cellspacing="2" cellpadding="5">
    <tr>
      <th width="33%" scope="row"><?php _e('Priority:', 'otd') ?></th>
      <td width="67%">
        <select name='otd_priority' class='postform'>
        <?php echo $selection; ?>
        </select>
      <input type="hidden" name="id" value="<?php echo $todo->id ?>" /></td>
    </tr>
    <tr>
      <th scope="row"><?php _e('Description:', 'otd') ?></th>
      <td>
       <textarea name="otd_description" 
       rows="5" cols="50" style="width:97%;"><?php echo wp_specialchars($todo->todotext, 1); ?></textarea>
      </td>
    </tr>
    </table>
    <p class="submit">
      <input type="hidden" name="otd_action" value="updatetd" />
      <input type="submit" name="submit" value="<?php _e('Update Todo', 'otd') ?>" />
    </p>
 </form>
 <p><a href="<?php echo $otd_location; ?>"><?php _e('&laquo; Return to todo list', 'otd'); ?></a></p>
</div>
<?php        
 }
 else 
 {
?>
<div class="wrap">   
<h2><?php _e('Our Todo List', 'otd'); ?> 
(<a href="#addtd"><?php _e('add new', 'otd'); ?></a>)</h2>
<table class="widefat" id="todo-list" width="100%" cellpadding="3" cellspacing="3">
  <thead>
  <tr>
     <th width="70%" colspan="2"><?php _e('Item', 'otd'); ?></th>
     <th><?php _e('Priority', 'otd'); ?></th>
     <th><?php _e('Last Edited By', 'otd'); ?></th>
     <th colspan="2"><?php _e('Action', 'otd'); ?></th>
  </tr>
  </thead>
  <tbody>
<?php
   $sql = "SELECT id, author, status, priority, todotext FROM ".
          $otd_tablename . " WHERE status = 0 ORDER BY priority";
   $results = $wpdb->get_results($sql);   
   if ($results)
   {
     foreach ($results as $result)
     {
       $user = get_userdata($result->author);
       $class = ('alternate' == $class) ? '' : 'alternate';
       $prstr = $priority[ $result->priority ];

       $edit = '<a href="' . $otd_location . '&otd_action=edittd&id='.
               $result->id . '" class="edit">'.__('Edit', 'otd') . '</a></td><td>'.
               '<a href="' . $otd_location . '&otd_action=trashtd&id='.
               $result->id . '" class="delete">'.__('Delete', 'otd').'</a>';
       
       echo "<tr id=\"otd-{$result->id}\" class=\"$class\">
       <td width=\"1%\" ><input type=\"checkbox\" id=\"td-{$result->id}\" 
       onclick=\"window.location='$otd_location&otd_action=comptd&id=$result->id';\" /></td>
       <td>{$result->todotext}</td>
       <td>$prstr</td>
       <td>{$user->display_name}</td>
       <td>$edit</td>
       </tr>";
     }
   } 
   else
   {
     echo '<tr><td colspan="3">'.__('There is nothing to do..', 'otd').'</td></tr>';
   }

?>
  </tbody>
</table>      
</div>

<div class="wrap">   
<h2><?php _e('Completed Tasks', 'otd'); ?> 
(<a href="<?php echo $otd_location; ?>&otd_action=purgetd"><?php _e('purge', 'otd'); ?></a>)</h2>
<table class="widefat" id="todo-list" width="100%" cellpadding="3" cellspacing="3">
    <thead>
    <tr>
      <th width="70%" colspan="2"><?php _e('Item', 'otd'); ?></th>
      <th><?php _e('Priority', 'otd'); ?></th>
      <th><?php _e('Last Edited By', 'otd'); ?></th>
      <th><?php _e('Action', 'otd'); ?></th>
    </tr>
    </thead>
    <tbody>
<?php
   $sql = "SELECT id, author, status, priority, todotext FROM ". 
          $otd_tablename . " WHERE status = 1 ORDER BY priority";
   $results = $wpdb->get_results($sql);   
   if ($results)
   {
     foreach ($results as $result)
     {
       $user = get_userdata($result->author);
       $class = ('alternate' == $class) ? '' : 'alternate';
       $prstr = $priority[ $result->priority ];
       $edit = '<a href="'. $otd_location . '&amp;otd_action=trashtd&amp;id='. 
               $result->id . '" class="delete">'.__('Delete', 'otd') . '</a>';
       
       echo "<tr id=\"otd-$result->id\" class=\"$class\">
       <td width=\"1%\"><input type=\"checkbox\" id=\"td-{$result->id}\" checked=\"checked\"
       onclick=\"window.location = '$otd_location&amp;otd_action=uncomptd&amp;id=$result->id';\" /></td>
       <td>{$result->todotext}</td>
       <td>$prstr</td>
       <td>{$user->display_name}</td>
       <td>$edit</td>
       </tr>";
     }
   } 
   else
   {
     echo '<tr><td colspan="4">'.__('There are no completed tasks.', 'otd').'</td></tr>';
   }
?>
   </tbody>
</table>      
</div>

<div class="wrap">
    <h2><?php _e('Add New Todo', 'otd') ?></h2>
    <form name="addtd" id="addtd" method="post">
        <p><?php _e('Priority:', 'otd') ?><br />
        <select name='otd_priority' class='postform'>
        <option value='0'><?php _e('Important', 'otd'); ?></option>
        <option value='1' selected="selected"><?php _e('Normal', 'otd'); ?></option>
        <option value='2'><?php _e('Low', 'otd'); ?></option>
        </select></p>
        <p><?php _e('Description:', 'otd') ?> <br />
        <textarea name="otd_description" rows="5" cols="50" style="width: 97%;"></textarea></p>
        <p class="submit">
          <input type="hidden" name="otd_action" value="addtodo" />
          <input type="submit" name="submit" value="<?php _e('Add Todo &raquo;', 'otd') ?>" />
        </p>
    </form>
</div>

<div class="wrap">
   <h2><?php _e('Install', 'otd') ?></h2>
   <p><?php printf(
__('If you are running Wordpress 1.5 you will need to run %sthis script%s to install the required database table.', 'otd'), 
'<a href="'.$otd_location.'&amp;otd_action=setuptd">', '</a>'); ?></p>
</div> 
<?php 
  }
}


/* Display top 10 items on Dashboard  */
function otd_todo_in_activity_box()
{
   global $otd_tablename, $wpdb, $otd_location;

   echo '<div><h3>'.__('Our Todo List', 'otd').
        ' <a href="' . $otd_location . '">'.
        __('&raquo;', 'otd').'</a></h3>';

   $sql = "SELECT id, author, todotext FROM " . $otd_tablename . 
          " WHERE status = 0 ORDER BY priority LIMIT 10";
   $results = $wpdb->get_results($sql);   
   if ($results)
   {
     echo '<ol>';
     foreach ($results as $result)
     {
        $user = get_userdata($result->author);
        echo "<li>$result->todotext <small>".
             '(<a href="'. $otd_location . '&otd_action=edittd&id=' . $result->id . '">'.
             __('Edit', 'otd')  . '</a>)</small> ~'.$user->display_name.'</li>';
     }
     echo '</ol>';
   } 
   else
   {
     echo '<p>'.__('There is nothing to do..', 'otd').'</p>'; 
   }
    echo '<p style="text-align:right">'.
         '<a href="' . $otd_location . '#addtd">'.
         __('New Todo &raquo;', 'otd').'</a></p></div>';
}



///////////////////////////  Developer APIs


/* Public CONSTANTS */
define('OTD_COMPLETED', 1);
define('OTD_TODO', 2);
define('OTD_ALL', OTD_COMPLETED+OTD_TODO);


/* Private function */
function otd_get_todo_list_($ret_bool=false, $status=OTD_TODO,
                            $limit=0, $show_priority=true, $show_author=true) {
  global $otd_tablename, $wpdb;

  $priority_table = array(0=> __('Important', 'otd') , 1 => __('Normal', 'otd'), 2=> __('Low', 'otd'));
  $limit  = (preg_match('/^[0-9]+$/', $limit) && $limit > 0) ? "LIMIT $limit" : '';

  switch ($status)
  {
    case OTD_TODO:
      $where = ' WHERE status = 0 ';
      break;
    case OTD_COMPLETED:
      $where = ' WHERE status = 1 ';
      break;
    case OTD_ALL:
    default:
      $where = '';
      break;
  }

  $sql = "SELECT author, todotext, priority, status FROM $otd_tablename ".
         "$where ORDER BY priority $limit";
  $results = $wpdb->get_results($sql);
  
  $t_out = '';
  if ($results) {
    if ($ret_bool) { 
      return true;
    }

    foreach ($results as $result) {
      $user = get_userdata($result->author);
      $author = ($show_author)
                ? ' <span class="otd_author">~ '.$user->display_name.'</span>'
                : '';
      $priority = ($show_priority)
                  ? ' <span class="otd_priority">('.
                    $priority_table[$result->priority].')</span>'
                  : '';
      $classname = (1 == $result->status)
                   ? 'otd_completed'
                   : 'otd_todo';

      $t_out .= "<li class=\"$classname\">$result->todotext$priority$author</li>";
    }
  }
  return $t_out;
}


/* Public functions  */

function ourtodolist_all($limit=0, $show_priority=false, $show_author=false) {
  return otd_get_todo_list_(false, OTD_ALL, $limit, $show_priority, $show_author);
}

function ourtodolist($limit=0, $show_priority=false, $show_author=false) {
  return otd_get_todo_list_(false, OTD_TODO, $limit, $show_priority, $show_author);
}

function ourtodolist_completed($limit=0, $show_priority=false, $show_author=false) {
  return otd_get_todo_list_(false, OTD_COMPLETED, $limit, $show_priority, $show_author);
}

function ourtodolist_exists($status=OTD_TODO) {
  /* backward-compatible - prior v1.7 */
  if (true === $status) { $status = OTD_COMPLETED; }
  else if (false === $status) { $status = OTD_TODO; }

  return otd_get_todo_list_(true, $status);
}


/////////////////////////  Misc

// Replace plugin_basename() in WP, taken from <http://trac.wordpress.org/ticket/4408>
function otd_plugin_basename ($file) 
{
    $file = str_replace('\\','/',$file); // sanitize for Win32 installs
    $file = preg_replace('|/+|','/', $file); // remove any duplicate slash
    $file = preg_replace('|^.*/wp-content/plugins/|','',$file); // get relative path from plugins dir
    return $file;
}


function generate_ourtodolist($content) {
	if (strpos($content, "<!-- ourtodolist_all -->") !== FALSE) {
		$content = str_replace('<!-- ourtodolist_all -->', ourtodolist(0, false, false), $content);
	}
	if (strpos($content, "<!-- ourtodolist -->") !== FALSE) {
		$content = str_replace('<!-- ourtodolist -->', ourtodolist(0, false, false), $content);
	}
	if (strpos($content, "<!-- ourtodolist_completed -->") !== FALSE) {
		$content = str_replace('<!-- ourtodolist_completed -->', ourtodolist_completed(0, false, false), $content);
	}
	return $content;
}

add_filter('the_content', 'generate_ourtodolist');